﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#ifndef __XOSKIT_XOS_CORE_XOS_STL_SRC_MEM_POOL_MEM_POOL_H__
#define __XOSKIT_XOS_CORE_XOS_STL_SRC_MEM_POOL_MEM_POOL_H__

#include "fake_lock.h"
#include "xos_list.h"

namespace xos_stl
{

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // mem_pool

    template< class T, class PoolLock, class ListLock = fake_lock >
    class mem_pool
    {
    public:
        typedef PoolLock POOL_LOCK;
        typedef ListLock LIST_LOCK;
        typedef xos_list< T, LIST_LOCK > LIST;
        typedef typename LIST::const_iterator CONST_ITER;
        typedef typename LIST::iterator ITER;

    protected:
        size_t _xos_stl_mem_pool_total_num;
        POOL_LOCK _xos_stl_mem_pool_lock;
        LIST _xos_stl_mem_pool_list;

    protected:
        void init_list( LIST & list, int nNum )
        {
            for( int i = 0; i < nNum; ++i )
            {
                _xos_stl_mem_pool_total_num++;
                T * p = new T;
                list.push_back( p );
            }
        }
        void term_list( LIST & list )
        {
            for( ITER i = list.begin(); i != list.end(); ++i )
            {
                _xos_stl_mem_pool_total_num--;
                T * pTemp = *i;
                delete pTemp;
            }
            list.clear();
        }
    public:
        mem_pool( int nNum )
        {
            _xos_stl_mem_pool_total_num = 0;
            init_list( _xos_stl_mem_pool_list, nNum );
        }
        mem_pool()
        {
            _xos_stl_mem_pool_total_num = 0;
        }
        ~mem_pool()
        {
            term_list( _xos_stl_mem_pool_list );
        }
        size_t get_total_count( bool bLock )
        {
            size_t num = 0;
            if( bLock )
            {
                lock();
            }
            num = _xos_stl_mem_pool_total_num;
            if( bLock )
            {
                un_lock();
            }
            return num;
        }
        size_t get_count( bool bLock )
        {
            size_t num = 0;
            if( bLock )
            {
                lock();
            }
            num = _xos_stl_mem_pool_list.size();
            if( bLock )
            {
                un_lock();
            }
            return num;
        }
        T * get_item( bool bLock )
        {
            T * pItem = 0;
            if( bLock )
            {
                lock();
            }
            if( _xos_stl_mem_pool_list.size() > 0 )
            {
                pItem = _xos_stl_mem_pool_list.front();
                _xos_stl_mem_pool_list.pop_front();
            }
            else
            {
                pItem = new T;
                _xos_stl_mem_pool_total_num++;
            }
            if( bLock )
            {
                un_lock();
            }
            return pItem;
        }
        void put_item( T * pT, bool bLock )
        {
            if( bLock )
            {
                lock();
            }
            _xos_stl_mem_pool_list.push_back( pT );
            if( bLock )
            {
                un_lock();
            }
        }
        void release_all( bool bLock )
        {
            if( bLock )
            {
                lock();
            }
            term_list( _xos_stl_mem_pool_list );
            if( bLock )
            {
                un_lock();
            }
        }
        void un_lock()
        {
            _xos_stl_mem_pool_lock.un_lock();
        }
        void lock()
        {
            _xos_stl_mem_pool_lock.lock();
        }

    };

} // xos_stl

#endif // __XOSKIT_XOS_CORE_XOS_STL_SRC_MEM_POOL_MEM_POOL_H__
